# -*- coding: utf-8 -*-
import win32com.client
import os
import logging
from utils import messager
import time

# 设置日志配置
current_dir = os.path.dirname(os.path.abspath(__file__))
target_dir = os.path.join(os.path.dirname(current_dir), "logs")  # 子目录名称
log_filename = os.path.join(target_dir, "attendance_device.log")
logging.basicConfig(
    level=logging.INFO,  # 设置日志级别为INFO
    format='%(asctime)s - %(levelname)s - %(message)s',  # 设置日志格式
    handlers=[
        logging.FileHandler(log_filename),  # 将日志写入文件
        logging.StreamHandler()  # 也打印到控制台
    ]
)

# 创建 zkemkeeper.ZKEM 对象
zkem = win32com.client.Dispatch("zkemkeeper.ZKEM")

# 考勤机连接信息
ip_address = "192.168.0.51"  # 考勤机的IP地址
port = 4370  # 考勤机的端口号

# 连接考勤机的函数
def connect_to_device(ip, port):
    max_retries = 3
    retry_delay = 1

    for attempt in range(max_retries):
        if zkem.Connect_Net(ip, port):
            logging.info(f"IP: {ip}成功连接考勤机")
            return True
        else:
            if attempt < max_retries - 1:
                logging.warning(f"连接考勤机失败，第 {attempt + 1} 次重试... (IP: {ip}:{port})")
                time.sleep(retry_delay)
            else:
                msge = f"创建用户，IP: {ip}:{port}连接考勤机失败，已重试 {max_retries} 次"
                messager.mesageuser(msge)
                logging.error(msge)
                return False

# def connect_to_device(ip, port):
#     if zkem.Connect_Net(ip, port):
#         logging.info(f"IP: {ip}成功连接考勤机")
#         return True
#     else:
#         msge = f"创建用户，IP: {ip}:{port}连接考勤机失败"
#         messager.mesageuser(msge)
#         logging.error(msge)
#         return False

# 创建或更新用户信息的函数
def create_user(dwMachineNumber, dwEnrollNumber, Name, Password, Privilege, Enabled):
    """
    创建或更新用户信息
    :param dwMachineNumber: 机器号，通常为1
    :param dwEnrollNumber: 用户号，唯一标识用户
    :param Name: 用户姓名
    :param Password: 用户密码
    :param Privilege: 用户权限
    :param Enabled: 用户启用标志
    :return: True 表示成功，False 表示失败
    """
    success = zkem.SSR_SetUserInfo(dwMachineNumber, dwEnrollNumber, Name, Password, Privilege, Enabled)
    if success:
        logging.info(f"用户 {Name} (ID: {dwEnrollNumber}) 创建或更新成功")
        return True
    else:
        logging.error(f"用户 {Name} (ID: {dwEnrollNumber}) 创建或更新失败")
        return False

# 删除用户信息的函数
def delete_user(dwMachineNumber, dwEnrollNumber, dwBackupNumber):
    """
    删除用户信息
    :param dwMachineNumber: 机器号，通常为1
    :param dwEnrollNumber: 用户号，唯一标识用户
    :return: True 表示成功，False 表示失败
    """
    success = zkem.SSR_DeleteEnrollData(dwMachineNumber, dwEnrollNumber, dwBackupNumber)
    if success:
        logging.info(f"用户ID: {dwEnrollNumber}) 删除成功")
        return True
    else:
        logging.error(f"用户ID: {dwEnrollNumber}) 删除失败")
        return False


# 重命名文件的函数
def rename_file(absolute_path, new_name):
    """
    将文件重命名为新名称
    :param absolute_path: 文件的绝对路径
    :param new_name: 新的文件名（包括扩展名）
    :return: 重命名后的文件路径，如果失败则返回 None
    """
    directory_path = os.path.dirname(absolute_path)
    new_path = os.path.join(directory_path, new_name)
    # 如果新路径和原路径相同，直接返回
    if absolute_path == new_path:
        return absolute_path
    # 检查目标文件是否已存在
    if os.path.exists(new_path):
        logging.info(f"目标文件已存在，先删除目标文件：{new_path}")
        os.remove(new_path)  # 先删除目标文件
        os.rename(absolute_path, new_path)
        logging.info(f"重命名成功：{absolute_path} -> {new_path}")
        return new_path
    try:
        os.rename(absolute_path, new_path)
        logging.info(f"重命名成功：{absolute_path} -> {new_path}")
        return new_path
    except Exception as e:
        logging.error(f"重命名失败：{e}")
        return None

# 发送用户人脸照片的函数
def send_user_face_photo(machine_number, file_name):
    """
    发送人脸照片到考勤机
    :param machine_number: 机器设备号
    :param file_name: 要发送的文件名（包括路径）
    :return: True 表示成功，False 表示失败
    """
    if not os.path.exists(file_name):
        logging.error(f"文件不存在: {file_name}")
        return False
    if zkem.SendUserFacePhoto(machine_number, file_name):
        logging.info(f"成功发送人脸照片: {file_name}")
        return True

    else:
        logging.error(f"发送人脸照片失败: {file_name}")
        return False


# 刷新考勤机数据的函数
def refresh_data(machine_number):
    """
    从考勤机读取文件
    :param machine_number: 机器设备号
    :return: True 表示成功，False 表示失败
    """
    if zkem.RefreshData(machine_number):
        logging.info(f"成功刷新考勤机数据")
        return True
    else:
        logging.error(f"刷新考勤机数据失败")
        return False


# 主函数
def main():
    # 连接设备
    if not connect_to_device(ip_address, port):
        return
    # 设置用户信息
    dwMachineNumber = 1  # 机器号，通常为1
    dwEnrollNumber = "T003"  # 用户号，唯一标识用户
    Name = "ZK测试人员"  # 用户姓名
    Password = ""  # 用户密码
    Privilege = 0  # 用户权限：0为普通用户
    Enabled = 1  # 用户启用标志：1为启用

    # 创建或更新用户
    if create_user(dwMachineNumber, dwEnrollNumber, Name, Password, Privilege, Enabled):
        # 如果用户创建成功，上传用户照片
        absolute_path = r"C:\Users\Administrator\Desktop\photos\20250321094606.jpg"  # 用户照片的绝对路径
        new_name = f"verify_biophoto_9_{dwEnrollNumber}.jpg"  # 新文件名
        FileName = rename_file(absolute_path, new_name)  # 重命名文件
        if FileName:
            if not send_user_face_photo(dwMachineNumber, FileName):
                logging.warning("上传用户照片失败，但将继续刷新考勤机数据")
    else:
        logging.warning("用户创建失败，跳过上传用户照片步骤")

    # 无论用户创建是否成功，都刷新考勤机数据
    if not refresh_data(dwMachineNumber):
        logging.error("刷新考勤机数据失败")

    # 断开连接
    zkem.Disconnect()
    logging.info("设备已断开连接!")

if __name__ == "__main__":
    main()
